home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / window.c < prev    next >
C/C++ Source or Header  |  1999-08-19  |  45KB  |  1,896 lines

  1. /****************************************************************************
  2.  *    window.c
  3.  *    Text mode window engine
  4.  *
  5.  *    Written by Neil Bradley (neil@synthcom.com)
  6.  *    Heavily modified by Juergen Buchmueller (pullmoll@t-online.de)
  7.  *
  8.  *  Designed to fit the needs of the new MAME debugger (a bit more ;)
  9.  *
  10.  *    Warning: This code is still buggy!
  11.  *    Some of the changes I made were contrary to the original design,
  12.  *    so expect 'assertions' for every non common case (ie. window too
  13.  *    big, hanging out of the screen etc.)
  14.  ****************************************************************************/
  15. #include <stdio.h>
  16.  
  17. #ifdef MAME_DEBUG
  18.  
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <stdarg.h>
  22. #include <assert.h>
  23. #include "window.h"
  24.  
  25. /*
  26.  * These standard definition functions are macro'd so they can easily be
  27.  * redefined to other custom procedures.
  28.  */
  29.  
  30. #define ASSERT(expr)    assert(expr)
  31.  
  32. INLINE void *MyMalloc( UINT32 size, const char *function )
  33. {
  34.     void *p = malloc( size );
  35.     ASSERT( p );
  36.     memset( p, 0, size );
  37.     return p;
  38. }
  39.  
  40. INLINE void *MyReAlloc( void *p, UINT32 size, const char *function )
  41. {
  42.     p = realloc( p, size );
  43.     ASSERT( p );
  44.     return p;
  45. }
  46.  
  47. INLINE void MyFree( void **p, const char *function )
  48. {
  49.     if( *p )
  50.     {
  51.         free(*p);
  52.         *p = NULL;
  53.     }
  54. }
  55.  
  56. /* Forward references for circular function calls */
  57.  
  58. void win_set_cursor_char(UINT32 idx, UINT32 state, UINT32 state_old);
  59.  
  60. /* Global windowing data we need */
  61.  
  62. UINT32 screen_w = 80;    /* Our screen's size in characters X */
  63. UINT32 screen_h = 50;    /* Our screen's size in characters Y */
  64.  
  65. static struct sWindow *p_windows = NULL;
  66. static UINT8 *p_prio_map = NULL;
  67. static UINT8 *p_shadow_map = NULL;
  68. static UINT8 *p_text = NULL;
  69. static UINT8 *p_attr = NULL;
  70.  
  71. /************************************************************************
  72.  *
  73.  * Name : win_out
  74.  *
  75.  * Entry: Character, attribute and X/Y position of char to place
  76.  *
  77.  * Exit : None
  78.  *
  79.  * Description:
  80.  *
  81.  * This routine will place a character at a given video position.
  82.  *
  83.  ************************************************************************/
  84.  
  85. INLINE void win_out(UINT8 bChar, UINT8 bAttr, UINT32 x, UINT32 y, UINT32 idx)
  86. {
  87.     UINT32 offs = (y * screen_w) + x;
  88.  
  89.     ASSERT(idx < MAX_WINDOWS);
  90.  
  91.     if( x >= screen_w || y >= screen_h )
  92.         return;
  93.  
  94.     idx = p_windows[idx].prio;
  95.  
  96.     /* If we're under the influence of a Window's shadow, change the attribute */
  97.     if( idx > p_shadow_map[offs] )
  98.         bAttr = ( bAttr & 0x08 ) ? bAttr & 0x07 : 0x08;
  99.  
  100.     /* If it's different */
  101.     if( bChar != p_text[offs] || bAttr != p_attr[offs] )
  102.     {
  103.         /* Put it in our video map */
  104.         p_text[offs] = bChar;
  105.         p_attr[offs] = bAttr;
  106.  
  107.         /* Here's where we draw the character */
  108.         osd_put_screen_char(bChar, bAttr, x, y);
  109.     }
  110. }
  111.  
  112. /************************************************************************
  113.  *
  114.  * Name : win_update_map
  115.  *
  116.  * Entry: Nothing
  117.  *
  118.  * Exit : Nothing
  119.  *
  120.  * Description:
  121.  *
  122.  * This routine will update the window priority map and
  123.  * will recompute all windows.
  124.  *
  125.  ************************************************************************/
  126.  
  127. static void win_update_map(void)
  128. {
  129.     INT32 prio, i;
  130.     UINT32 yadd, xadd, x, y;
  131.     struct sWindow *pwin;
  132.  
  133.     ASSERT(p_prio_map); /* This had better not be null */
  134.     ASSERT(p_windows);    /* This either */
  135.  
  136.     memset(p_prio_map, 0xff, screen_w * screen_h);
  137.  
  138.     for( prio = 0xff; prio >= 0; prio-- )
  139.     {
  140.         for( i = 0, pwin = p_windows; i < MAX_WINDOWS; i++, pwin++ )
  141.         {
  142.             if ( pwin->prio == prio && pwin->text && !(pwin->flags & HIDDEN) )
  143.                 break;
  144.         }
  145.  
  146.         if( i != MAX_WINDOWS && pwin->x < screen_w )
  147.         {
  148.             UINT32 w;
  149.             xadd = 0;
  150.             yadd = 0;
  151.  
  152.             if( pwin->flags & BORDER_LEFT )   ++xadd;
  153.             if( pwin->flags & BORDER_RIGHT )  ++xadd;
  154.             if( pwin->flags & BORDER_TOP )      ++yadd;
  155.             if( pwin->flags & BORDER_BOTTOM ) ++yadd;
  156.  
  157.             w = pwin->w + xadd;
  158.             if( w > screen_w )
  159.                 w = screen_w - pwin->x;
  160.  
  161.             for( y = pwin->y; y < screen_h && y < pwin->y + pwin->h + yadd; y++ )
  162.                 memset(&p_prio_map[y * screen_w + pwin->x], prio, w);
  163.         }
  164.     }
  165.  
  166.     /* Now create a shadow region (if applicable) */
  167.  
  168.     memset(p_shadow_map, 0xff, screen_w * screen_h);
  169.  
  170.     for( pwin = &p_windows[MAX_WINDOWS-1], i = MAX_WINDOWS-1; i >= 0; --i, --pwin )
  171.     {
  172.         /* Let's figure out if we should be doing a shadow */
  173.  
  174.         if( pwin->text && (pwin->flags & SHADOW) && !(pwin->flags & HIDDEN) )
  175.         {
  176.             yadd = pwin->y + pwin->h;
  177.             xadd = pwin->x + pwin->w;
  178.  
  179.             /* If we have additional borders, extend it! */
  180.             if( pwin->flags & BORDER_TOP )      ++yadd;
  181.             if( pwin->flags & BORDER_BOTTOM ) ++yadd;
  182.             if( pwin->flags & BORDER_LEFT )   ++xadd;
  183.             if( pwin->flags & BORDER_RIGHT )  ++xadd;
  184.  
  185.             /* If the line is still within range, go figure it! */
  186.  
  187.             if( (yadd + 1) < screen_h )
  188.             {
  189.                 for( x = pwin->x + 1; x < screen_w && x < (xadd + 1); x++ )
  190.                 {
  191.                     if( pwin->prio < p_shadow_map[x + (yadd * screen_w)] )
  192.                         p_shadow_map[x + (yadd * screen_w)] = pwin->prio;
  193.                 }
  194.             }
  195.  
  196.             /* Now let's draw us a vertical shadow line */
  197.             if( (xadd + 1) < screen_w )
  198.             {
  199.                 for( y = pwin->y + 1; y < yadd; y++ )
  200.                 {
  201.                     if( pwin->prio < p_shadow_map[xadd + (y * screen_w)] )
  202.                         p_shadow_map[xadd + (y * screen_w)] = pwin->prio;
  203.                 }
  204.             }
  205.         }
  206.     }
  207. }
  208.  
  209. /************************************************************************
  210.  *
  211.  * Name : win_update_shadow
  212.  *
  213.  * Entry: Window #, pointer to an array of bytes for affected windows
  214.  *
  215.  * Exit : Nothing
  216.  *
  217.  * Description:
  218.  *
  219.  * This routine will find all windows that are affected by a
  220.  * shadow of a given window. Not actual updates are done.
  221.  *
  222.  ************************************************************************/
  223.  
  224. static void win_update_shadow(UINT32 idx, UINT8 *affected)
  225. {
  226.     struct sWindow *pwin = &p_windows[idx];
  227.     UINT32 x, y, xadd, yadd;
  228.     UINT8 bMap = 0;
  229.  
  230.     xadd = pwin->w;
  231.     yadd = pwin->h;
  232.  
  233.     if( pwin->flags & BORDER_LEFT )   ++xadd;
  234.     if( pwin->flags & BORDER_RIGHT )  ++xadd;
  235.     if( pwin->flags & BORDER_TOP )      ++yadd;
  236.     if( pwin->flags & BORDER_BOTTOM ) ++yadd;
  237.  
  238.     /* Now check to see if we need to update anything because of the shadow */
  239.  
  240.     if( pwin->flags & SHADOW )
  241.     {
  242.         /* Check out the shadow on the bottom and see if we need */
  243.         /* to update a window below. */
  244.         y = yadd + pwin->y;
  245.         if( y < screen_h )
  246.         {
  247.             for( x = pwin->x + 2; x < (pwin->x + xadd + 2); x++ )
  248.             {
  249.                 if( x < screen_w )
  250.                 {
  251.                     bMap = p_prio_map[(y * screen_w) + x];
  252.                     if( 0xff != bMap )
  253.                         affected[bMap] = 1;
  254.                 }
  255.             }
  256.         }
  257.  
  258.         /* And now down the right side */
  259.         for( y = pwin->y + 1; y < screen_h && y < pwin->y + yadd + 1; y++ )
  260.         {
  261.             for( x = xadd + pwin->x; x < (xadd + pwin->x + 2); x++ )
  262.             {
  263.                 if( x < screen_w )
  264.                 {
  265.                     bMap = p_prio_map[(y * screen_w) + x];
  266.                     if( 0xff != bMap )
  267.                         affected[bMap] = 1;
  268.                 }
  269.             }
  270.         }
  271.     }
  272. }
  273.  
  274. /************************************************************************
  275.  *
  276.  * Name : win_update
  277.  *
  278.  * Entry: Window # to update
  279.  *
  280.  * Exit : Nothing
  281.  *
  282.  * Description:
  283.  *
  284.  * This routine will update a given window on the screen.
  285.  *
  286.  ************************************************************************/
  287.  
  288. void win_update(UINT32 idx)
  289. {
  290.     struct sWindow *pwin = &p_windows[idx];
  291.     UINT8 affected[MAX_WINDOWS];
  292.     UINT32 x0, y0, x, y, win_offs, scr_offs;
  293.     UINT8 ch, color;
  294.  
  295.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  296.     ASSERT(p_windows);            /* And this had better be initialized */
  297.  
  298.     memset( affected, 0, sizeof(affected) );
  299.  
  300.     /* If this isn't a valid window or it's hidden, just bail out */
  301.  
  302.     if( NULL == pwin->text || (pwin->flags & HIDDEN) )
  303.         return;
  304.  
  305.     /* Let's whip through and draw the whole stinking window, shall we? */
  306.  
  307.     x0 = pwin->x;
  308.     y0 = pwin->y;
  309.  
  310.     if( pwin->flags & BORDER_LEFT ) ++x0;
  311.     if( pwin->flags & BORDER_TOP )    ++y0;
  312.  
  313.     color = pwin->co_frame;
  314.  
  315.     /* See if we need a character in the upper left hand corner of our window */
  316.     if( (pwin->flags & BORDER_TOP) && (pwin->flags & BORDER_LEFT) )
  317.     {
  318.         if( pwin->x < screen_w && pwin->y < screen_h )
  319.             if( p_prio_map[pwin->x + (pwin->y * screen_w)] >= pwin->prio )
  320.                 win_out(FRAME_TL, color, pwin->x, pwin->y, idx);
  321.     }
  322.  
  323.     /* See if we need a character in the lower left hand corner of our window */
  324.     if( (pwin->flags & BORDER_BOTTOM) && (pwin->flags & BORDER_LEFT) )
  325.     {
  326.         if( pwin->x < screen_w && pwin->y + y0 < screen_h )
  327.             if( p_prio_map[pwin->x + ((y0 + pwin->h) * screen_w)] >= pwin->prio )
  328.                 win_out(FRAME_BL, color, pwin->x, pwin->h + y0, idx);
  329.     }
  330.  
  331.     /* See if we need a character in the upper right hand corner of our window */
  332.     if( (pwin->flags & BORDER_TOP) && (pwin->flags & BORDER_RIGHT) )
  333.     {
  334.         if( pwin->x + x0 < screen_w && pwin->y < screen_h )
  335.             if( p_prio_map[pwin->w + x0 + (pwin->y * screen_w)] >= pwin->prio )
  336.                 win_out(FRAME_TR, color, pwin->w + x0, pwin->y, idx);
  337.     }
  338.  
  339.     /* See if we need a character in the lower right hand corner of our window */
  340.     if( (pwin->flags & BORDER_BOTTOM) && (pwin->flags & BORDER_RIGHT) )
  341.     {
  342.         if( pwin->x + x0 < screen_w && pwin->y + y0 < screen_h )
  343.             if( p_prio_map[pwin->w + x0 + ((pwin->h + y0) * screen_w)] >= pwin->prio )
  344.                 win_out(FRAME_BR, color, pwin->w + x0, pwin->h + y0, idx);
  345.     }
  346.  
  347.     /* Let's go through and draw the frame for the window (if any) */
  348.     if( pwin->flags & BORDER_LEFT )    /* Here we have a left border */
  349.     {
  350.         for( y = y0; y < (y0 + pwin->h); y++ )
  351.         {
  352.             if( p_prio_map[pwin->x + (y * screen_w)] >= pwin->prio )
  353.                 win_out(FRAME_V, color, pwin->x, y, idx);
  354.         }
  355.     }
  356.  
  357.     /* Let's draw the right side of the window (if any) */
  358.     if( pwin->flags & BORDER_RIGHT ) /* Here we have a right border */
  359.     {
  360.         if( pwin->w + x0 < screen_w )
  361.             for( y = y0; y < screen_h && y < (y0 + pwin->h); y++ )
  362.             {
  363.                 if( p_prio_map[pwin->w + x0 + (y * screen_w)] >= pwin->prio )
  364.                     win_out(FRAME_V, color, x0 + pwin->w, y, idx);
  365.             }
  366.     }
  367.  
  368.     /* Let's draw the bottom side of the window (if any) */
  369.     if( pwin->flags & BORDER_BOTTOM )
  370.     {
  371.         if( pwin->h + y0 < screen_h )
  372.             for( x = x0; x < (x0 + pwin->w); x++ )
  373.             {
  374.                 if( p_prio_map[((y0 + pwin->h) * screen_w) + x] >= pwin->prio )
  375.                     win_out(FRAME_H, color, x, y0 + pwin->h, idx);
  376.             }
  377.     }
  378.  
  379.     /* And now the top! */
  380.     if( pwin->flags & BORDER_TOP )
  381.     {
  382.         /* If we've got a title, let's put that in, too... */
  383.         if( pwin->title )
  384.         {
  385.             UINT32 i, j, length1, length2;
  386.             char *p = strchr(pwin->title, '\t');
  387.  
  388.             /* If the title contains a tab, split it into two parts */
  389.             if( p )
  390.             {
  391.                 i = 0;
  392.                 j = 1;
  393.                 length1 = (UINT32)(p - pwin->title);
  394.                 length2 = strlen(p + j);
  395.  
  396.                 for( x = x0; x < screen_w && x < (x0 + pwin->w); x++ )
  397.                 {
  398.                     if( p_prio_map[x + (pwin->y * screen_w)] < pwin->prio )
  399.                         continue;
  400.                     color = pwin->co_frame;
  401.                     if( x < (x0 + 1) )
  402.                     {
  403.                         ch = FRAME_H;
  404.                     }
  405.                     else
  406.                     if( x > (x0 + 1 + length1 + 1) )
  407.                     {
  408.                         if( x < (x0 + pwin->w - 1 - length2 - 1) )
  409.                         {
  410.                             ch = FRAME_H;
  411.                         }
  412.                         else
  413.                         {
  414.                             if( x == (x0 + pwin->w - 1) )
  415.                                 ch = CAPTION_R;
  416.                             else
  417.                             if( x == (x0 + pwin->w - 1 - length2 - 1) )
  418.                                 ch = CAPTION_L;
  419.                             else
  420.                             {
  421.                                 color = pwin->co_title;
  422.                                 ch = p[j++];
  423.                             }
  424.                         }
  425.                     }
  426.                     else
  427.                     {
  428.                         if( x == (x0 + 1) )
  429.                             ch = CAPTION_L;
  430.                         else
  431.                         if( x == (x0 + 1 + length1 + 1) )
  432.                             ch = CAPTION_R;
  433.                         else
  434.                         {
  435.                             color = pwin->co_title;
  436.                             ch = pwin->title[i++];
  437.                         }
  438.                     }
  439.                     win_out(ch, color, x, pwin->y, idx);
  440.                 }
  441.             }
  442.             else
  443.             {
  444.                 /* Draw a top border with a title in the left part */
  445.                 length1 = strlen(pwin->title);
  446.                 i = 0;
  447.                 for( x = x0; x < screen_w && x < (x0 + pwin->w); x++ )
  448.                 {
  449.                     if( p_prio_map[x + (pwin->y * screen_w)] < pwin->prio )
  450.                         continue;
  451.                     color = pwin->co_frame;
  452.                     if( x < (x0 + 1) || x > (x0 + 1 + length1 + 1) )
  453.                     {
  454.                         ch = FRAME_H;
  455.                     }
  456.                     else
  457.                     {
  458.                         if( x == (x0 + 1) )
  459.                             ch = CAPTION_L;
  460.                         else
  461.                         if( x == (x0 + 1 + length1 + 1) )
  462.                             ch = CAPTION_R;
  463.                         else
  464.                         {
  465.                             color = pwin->co_title;
  466.                             ch = pwin->title[i++];
  467.                         }
  468.                     }
  469.                     win_out(ch, color, x, pwin->y, idx);
  470.                 }
  471.             }
  472.         }
  473.         else
  474.         {
  475.             for( x = x0; x < screen_w && x < (x0 + pwin->w); x++ )
  476.             {
  477.                 if( p_prio_map[(pwin->y * screen_w) + x] >= pwin->prio )
  478.                     win_out(FRAME_H, color, x, pwin->y, idx);
  479.             }
  480.         }
  481.  
  482.     }
  483.  
  484.     /* Loop through our existing window and update it on the screen */
  485.     for( y = 0; y < pwin->h; y++ )
  486.     {
  487.         win_offs = y * screen_w;
  488.         scr_offs = (y0 + y) * screen_w + x0;
  489.         for( x = 0; x < pwin->w; x++ )
  490.         {
  491.             if( p_prio_map[scr_offs] >= pwin->prio )
  492.             {
  493.                 ch = pwin->text[win_offs];
  494.                 color = pwin->attr[win_offs];
  495.                 win_out(ch, color, x0 + x, y0 + y, idx);
  496.             }
  497.             win_offs++;
  498.             scr_offs++;
  499.         }
  500.     }
  501. }
  502.  
  503. /************************************************************************
  504.  *
  505.  * Name : win_erase
  506.  *
  507.  * Entry: Window index # to erase
  508.  *
  509.  * Exit : Nothing
  510.  *
  511.  * Description:
  512.  *
  513.  * This routine will erase a window from the physical display (including
  514.  * borders if applicable)
  515.  *
  516.  ************************************************************************/
  517.  
  518. void win_erase(UINT32 idx)
  519. {
  520.     struct sWindow *pwin = &p_windows[idx];
  521.     UINT8 affected[MAX_WINDOWS];
  522.     UINT32 i = 0;
  523.     UINT32 flags_old;
  524.     UINT8 bMap = 0;
  525.     UINT32 x, y;
  526.     UINT32 xadd = 0;
  527.     UINT32 yadd = 0;
  528.  
  529.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  530.     ASSERT(p_windows);            /* And this had better be initialized */
  531.  
  532.     if( NULL == pwin->text )
  533.         return;
  534.  
  535.     memset( affected, 0, sizeof(affected) );
  536.  
  537.     /* Let's fake like the window is gone */
  538.  
  539.     flags_old = pwin->flags;
  540.     pwin->flags |= HIDDEN;
  541.  
  542.     /* Recompute the display matrix */
  543.  
  544.     win_update_map();
  545.  
  546.     xadd = pwin->w;
  547.     yadd = pwin->h;
  548.  
  549.     if( pwin->flags & BORDER_LEFT )   ++xadd;
  550.     if( pwin->flags & BORDER_RIGHT )  ++xadd;
  551.     if( pwin->flags & BORDER_TOP )      ++yadd;
  552.     if( pwin->flags & BORDER_BOTTOM ) ++yadd;
  553.  
  554.     win_set_cursor_char(idx, 0, pwin->flags & CURSOR_ON);
  555.  
  556.     /* Go see if we need to do anything about our shadows */
  557.     for( y = pwin->y; y < screen_h && y < (pwin->y + yadd); y++ )
  558.     {
  559.         for( x = pwin->x; x < screen_w && x < (pwin->x + xadd); x++ )
  560.         {
  561.             bMap = p_prio_map[(y * screen_w) + x];
  562.             if( 0xff == bMap )
  563.                 win_out(WIN_EMPTY, WIN_WHITE, x, y, idx);
  564.             else
  565.                 affected[bMap] = 1;
  566.         }
  567.     }
  568.  
  569.     win_update_shadow(idx, affected);
  570.  
  571.     /* Now that we've erased the residuals, let's go update */
  572.     /* the windows that need it */
  573.  
  574.     for( i = 0; i < MAX_WINDOWS; i++ )
  575.     {
  576.         if( affected[i] || (i != idx) )
  577.         {
  578.             win_update(i);
  579.             win_set_cursor_char(i, p_windows[i].flags & CURSOR_ON, 0);
  580.         }
  581.     }
  582.  
  583.     pwin->flags = flags_old;
  584. }
  585.  
  586. /************************************************************************
  587.  *
  588.  * Name : win_set_cursor_char
  589.  *
  590.  * Entry: Window # to set cursor state, and state of cursor
  591.  *
  592.  * Exit : Nothing
  593.  *
  594.  * Description:
  595.  *
  596.  * This routine will either turn on/off the cursor in a given window.
  597.  *
  598.  ************************************************************************/
  599.  
  600. void win_set_cursor_char(UINT32 idx, UINT32 state, UINT32 state_old)
  601. {
  602.     struct sWindow *pwin = &p_windows[idx];
  603.     UINT32 x0, y0, win_offs;
  604.  
  605.     if( INVALID == idx )
  606.         return;
  607.  
  608.     if( NULL == pwin->text )
  609.         return;
  610.  
  611.     if( pwin->flags & HIDDEN )
  612.         return;
  613.  
  614.     if( pwin->flags & NO_WRAP )
  615.     {
  616.         if( pwin->x >= pwin->w )
  617.             return;
  618.         if( pwin->y >= pwin->h )
  619.             return;
  620.     }
  621.  
  622.     x0 = pwin->x + pwin->cx;
  623.     y0 = pwin->y + pwin->cy;
  624.  
  625.     if( pwin->flags & BORDER_LEFT ) ++x0;
  626.     if( pwin->flags & BORDER_TOP )    ++y0;
  627.  
  628.     /* If we are outside of the physical screen, just exit */
  629.     if( x0 >= screen_w || y0 >= screen_h )
  630.         return;
  631.  
  632.     win_offs = y0 * screen_w + x0;
  633.  
  634.     if( p_prio_map[win_offs] < pwin->prio )
  635.         return;
  636.  
  637.     if( state )
  638.     {
  639.         pwin->saved_text = p_text[win_offs];
  640.         pwin->saved_attr = p_attr[win_offs];
  641.         win_out(CHAR_CURSORON, WIN_BRIGHT_WHITE, x0, y0, idx);
  642.     }
  643.     else
  644.     {
  645.         if( 0 != state_old )
  646.             win_out(pwin->saved_text, pwin->saved_attr, x0, y0, idx);
  647.     }
  648. }
  649.  
  650. /************************************************************************
  651.  *
  652.  * Name : win_is_initalized()
  653.  *
  654.  * Entry: Nothing
  655.  *
  656.  * Exit : TRUE if a window is already initialized
  657.  *
  658.  * Description:
  659.  *
  660.  * This routine returns the initialization status of a window
  661.  *
  662.  ************************************************************************/
  663.  
  664. UINT32 win_is_initalized(UINT32 idx)
  665. {
  666.     struct sWindow *pwin = &p_windows[idx];
  667.  
  668.     if( !p_windows )
  669.         return FALSE;
  670.  
  671.     if( idx >= MAX_WINDOWS )
  672.         return FALSE;
  673.     if( pwin->text == NULL )
  674.         return FALSE;
  675.     if( pwin->attr == NULL )
  676.         return FALSE;
  677.  
  678.     return TRUE;
  679. }
  680.  
  681. /************************************************************************
  682.  *
  683.  * Name : win_init_engine()
  684.  *
  685.  * Entry: Nothing
  686.  *
  687.  * Exit : Nothing
  688.  *
  689.  * Description:
  690.  *
  691.  * This routine will initialize all variables needed for the windowing
  692.  * engine to start.
  693.  *
  694.  ************************************************************************/
  695.  
  696. UINT32 win_init_engine(UINT32 w, UINT32 h)
  697. {
  698.     UINT32 x, y;
  699.  
  700.     /* Uninitialize if we are currently initialized */
  701.  
  702.     win_exit_engine();    /* Just in case! */
  703.  
  704.     screen_w = w;
  705.     screen_h = h;
  706.  
  707.     /* Allocate memory for some things */
  708.  
  709.     p_text = MyMalloc(screen_w * screen_h, "win_init_engine()");
  710.     p_attr = MyMalloc(screen_w * screen_h, "win_init_engine()");
  711.     p_windows = MyMalloc(sizeof(struct sWindow) * MAX_WINDOWS, "win_init_engine()");
  712.     p_prio_map = MyMalloc(screen_w * screen_h, "win_init_engine()");
  713.     p_shadow_map = MyMalloc(screen_w * screen_h, "win_init_engine()");
  714.  
  715.     win_update_map();
  716.  
  717.     for (y = 0; y < screen_h; y++)
  718.         for (x = 0; x < screen_w; x++)
  719.             win_out(WIN_EMPTY, WIN_WHITE, x, y, 0);
  720.  
  721.     return(TRUE);
  722. }
  723.  
  724. /************************************************************************
  725.  *
  726.  * Name : win_exit_engine
  727.  *
  728.  * Entry: Nothing
  729.  *
  730.  * Exit : Nothing
  731.  *
  732.  * Description:
  733.  *
  734.  * This routine will shut down the windowing engine
  735.  *
  736.  ************************************************************************/
  737.  
  738. void win_exit_engine(void)
  739. {
  740.     UINT32 x, y, i;
  741.  
  742.     /* Clear the screen. This *MUST* be before the shadow map is freed! */
  743.  
  744.     if( p_windows )
  745.     {
  746.         if( p_text )
  747.         {
  748.             for (y = 0; y < screen_h; y++)
  749.                 for (x = 0; x < screen_w; x++)
  750.                     win_out(' ', WIN_WHITE, x, y, 0);
  751.         }
  752.  
  753.         for (i = 0; i < MAX_WINDOWS; i++)
  754.         {
  755.             if( p_windows[i].text )
  756.                 MyFree((void **) &p_windows[i].text, "win_exit_engine()");
  757.             if( p_windows[i].attr )
  758.                 MyFree((void **) &p_windows[i].attr, "win_exit_engine()");
  759.         }
  760.     }
  761.  
  762.     if( p_windows )
  763.         MyFree((void **) &p_windows, "InitWindowEngine()");
  764.     if(  p_prio_map )
  765.         MyFree((void **) &p_prio_map, "InitWindowEngine()");
  766.     if( p_shadow_map )
  767.         MyFree((void **) &p_shadow_map, "InitWindowEngine()");
  768.     if( p_text )
  769.         MyFree((void **) &p_text, "InitWindowEngine()");
  770.     if( p_attr )
  771.         MyFree((void **) &p_attr, "InitWindowEngine()");
  772. }
  773.  
  774. /************************************************************************
  775.  *
  776.  * Name : win_open
  777.  *
  778.  * Entry: Window structure, and priority desired
  779.  *
  780.  * Exit : FALSE If couldn't be opened, or TRUE if successful
  781.  *
  782.  * Description:
  783.  *
  784.  * This routine will allow one to open a window.
  785.  *
  786.  ************************************************************************/
  787.  
  788. UINT32 win_open(UINT32 idx, struct sWindow *psWin)
  789. {
  790.     struct sWindow *pwin = &p_windows[idx];
  791.     UINT8 affected[MAX_WINDOWS];
  792.     UINT32 xadd, yadd, i;
  793.     UINT8 ch = 0, color = 0;
  794.  
  795.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  796.     ASSERT(p_windows);            /* And this had better be initialized */
  797.     ASSERT(psWin);                /* This, too. */
  798.  
  799.     memset( affected, 0, sizeof(affected) );
  800.  
  801.     /* Is the window already open? Return FALSE if so */
  802.  
  803.     if( pwin->text )
  804.         return(FALSE);
  805.  
  806.     xadd = 0;
  807.     yadd = 0;
  808.  
  809.     if( psWin->flags & BORDER_LEFT )
  810.         ++xadd;
  811.     if( psWin->flags & BORDER_RIGHT )
  812.         ++xadd;
  813.     if( psWin->flags & BORDER_TOP )
  814.         ++yadd;
  815.     if( psWin->flags & BORDER_BOTTOM )
  816.         ++yadd;
  817.  
  818.     ASSERT((psWin->x + psWin->w + xadd) <= screen_w);
  819.     ASSERT((psWin->y + psWin->h + yadd) <= screen_h);
  820.  
  821.     psWin->text = MyMalloc( screen_w * (yadd + psWin->h), "win_open()" );
  822.     psWin->attr = MyMalloc( screen_w * (yadd + psWin->h), "win_open()" );
  823.     psWin->title = MyMalloc( screen_w + 1, "win_open()" );
  824.  
  825.     /* This is our fill character */
  826.     ch = psWin->filler;
  827.     color = psWin->co_text;
  828.  
  829.     for (i = 0; i < screen_w * (yadd + psWin->h); i++)
  830.     {
  831.         psWin->text[i] = ch;
  832.         psWin->attr[i] = color;
  833.     }
  834.  
  835.     psWin->cx = 0;
  836.     psWin->cy = 0;
  837.  
  838.     /* Copy it into the regular structure, update the window map and show */
  839.     /* the window (if it's not hidden) */
  840.  
  841.     memcpy(pwin, psWin, sizeof(struct sWindow));
  842.  
  843.     win_update_map();
  844.     win_update_shadow(idx, affected);
  845.  
  846.     /* Now that we've erased the residuals, let's go update the windows */
  847.     /* that need it */
  848.  
  849.     for (i = 0; i < MAX_WINDOWS; i++)
  850.     {
  851.         if( affected[i] || (i == idx) )
  852.         {
  853.             win_update(i);
  854.             win_set_cursor_char(i, p_windows[i].flags & CURSOR_ON, 0);
  855.         }
  856.     }
  857.  
  858.     pwin->saved_text = ch;
  859.     pwin->saved_attr = color;
  860.     win_set_cursor_char(idx, pwin->flags & CURSOR_ON, 0);
  861.  
  862.     /* Now that the window is opened, if there's a resize handler available, */
  863.     /* call it! */
  864.  
  865.     if( pwin->Resize )
  866.         pwin->Resize(idx, pwin);
  867.  
  868.     return(TRUE);
  869. }
  870.  
  871. /************************************************************************
  872.  *
  873.  * Name : win_close
  874.  *
  875.  * Entry: Window #
  876.  *
  877.  * Exit : Nothing
  878.  *
  879.  * Description:
  880.  *
  881.  * This routine will close down a currently opened window and erase it from
  882.  * the visual screen.
  883.  *
  884.  ************************************************************************/
  885.  
  886. void win_close(UINT32 idx)
  887. {
  888.     struct sWindow *pwin = &p_windows[idx];
  889.  
  890.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  891.     ASSERT(p_windows);            /* And this had better be initialized */
  892.  
  893.     if( NULL == pwin->text )
  894.         return;
  895.  
  896.     /* Call the shutdown client if applicable */
  897.  
  898.     if( pwin->Close )
  899.     {
  900.         if( FALSE == pwin->Close(idx, pwin) )
  901.             return;
  902.     }
  903.  
  904.     /* Erase the window from the screen */
  905.  
  906.     win_erase(idx);
  907.  
  908.     /* Delete all we've allocated */
  909.  
  910.     MyFree((void **) &pwin->text, "win_close()"); /* Free our video data */
  911.     MyFree((void **) &pwin->attr, "win_close()"); /* Free our video data */
  912.     MyFree((void **) &pwin->title, "win_close()"); /* Free our video data */
  913. }
  914.  
  915. /************************************************************************
  916.  *
  917.  * Name : win_scroll
  918.  *
  919.  * Entry: Window # to scroll
  920.  *
  921.  * Exit : Window is scrolled and updated (if currently visible)
  922.  *
  923.  * Description:
  924.  *
  925.  * This routine will scroll a window
  926.  *
  927.  ************************************************************************/
  928.  
  929. UINT32 win_scroll(UINT32 idx)
  930. {
  931.     struct sWindow *pwin = &p_windows[idx];
  932.     UINT32 i;
  933.     UINT8 *ptext, *pattr, color;
  934.  
  935.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  936.     ASSERT(p_windows);            /* And this had better be initialized */
  937.  
  938.     /* Is the window already open? Return FALSE if so */
  939.  
  940.     if( NULL == pwin->text )
  941.         return(FALSE);
  942.  
  943.     /* If we don't scroll it, don't scroll it! */
  944.  
  945.     if( pwin->flags & NO_SCROLL )
  946.         return(FALSE);
  947.  
  948.     /* Let's do the scroll */
  949.  
  950.     ptext = pwin->text;
  951.     pattr = pwin->attr;
  952.  
  953.     if( pwin->h != 1 )
  954.     {
  955.         memcpy( ptext, ptext + screen_w, screen_w * (pwin->h - 1) );
  956.         memcpy( pattr, pattr + screen_w, screen_w * (pwin->h - 1) );
  957.     }
  958.  
  959.     /* Now that we've done the scroll, let's clear out the bottom line */
  960.  
  961.     color = pwin->co_text;
  962.     for (i = 0; i < pwin->w; i++)
  963.     {
  964.         *ptext++ = ' ';
  965.         *pattr++ = color;
  966.     }
  967.  
  968.     win_update(idx);
  969.     return(TRUE);
  970. }
  971.  
  972. /************************************************************************
  973.  *
  974.  * Name : win_internal_putchar
  975.  *
  976.  * Entry: Character to display
  977.  *
  978.  * Exit : relative offset of the cursor after the output
  979.  *
  980.  * Description:
  981.  *
  982.  * This routine will put a character to the currently active window. This
  983.  * routine does not take into account the cursor! Use win_putc or win_printf
  984.  * instead!
  985.  *
  986.  ************************************************************************/
  987.  
  988. INT32 win_internal_putchar(UINT32 idx, UINT8 ch)
  989. {
  990.     struct sWindow *pwin = &p_windows[idx];
  991.     INT32 rel = 0;
  992.     UINT32 x0, y0;
  993.     UINT8 color;
  994.  
  995.     if( NULL == pwin->text )
  996.         return 0;
  997.  
  998.     color = pwin->co_text;
  999.  
  1000.     switch( ch )
  1001.     {
  1002.     case '\b':  /* Backspace? */
  1003.         if( pwin->cx )
  1004.         {
  1005.             pwin->cx--;
  1006.             rel--;
  1007.         }
  1008.         break;
  1009.  
  1010.     case '\r':  /* Carriage return */
  1011.         rel = - pwin->cx;
  1012.         pwin->cx = 0;
  1013.         break;
  1014.  
  1015.     case '\n':  /* Newline or linefeed? */
  1016. #if NEWLINE_ERASE_EOL
  1017.         win_erase_eol( idx, ' ' );
  1018. #endif
  1019.         rel = - pwin->cx;
  1020.         pwin->cx = 0;
  1021.         pwin->cy++;
  1022.         if( pwin->cy >= pwin->h )
  1023.         {
  1024.             pwin->cy--;
  1025.             win_scroll(idx);
  1026.         }
  1027.         break;
  1028.  
  1029.     case '\t':  /* Tab? */
  1030.         do
  1031.         {
  1032.             rel += win_internal_putchar( idx, ' ');
  1033.         } while( pwin->cx % TAB_STOP );
  1034.         break;
  1035.  
  1036.     default:
  1037.         x0 = pwin->x + pwin->cx;
  1038.         y0 = pwin->y + pwin->cy;
  1039.  
  1040.         if( pwin->flags & BORDER_LEFT )
  1041.             ++x0;
  1042.         if( pwin->flags & BORDER_TOP )
  1043.             ++y0;
  1044.  
  1045.         /* Sanity check */
  1046.         if( x0 < screen_w && y0 < screen_h )
  1047.         {
  1048.             pwin->text[pwin->cy * screen_w + pwin->cx] = ch;
  1049.             pwin->attr[pwin->cy * screen_w + pwin->cx] = color;
  1050.             if( pwin->cx < pwin->w )
  1051.             {
  1052.                 if( p_prio_map[y0 * screen_w + x0] >= pwin->prio && !(pwin->flags & HIDDEN) )
  1053.                     win_out(ch, color, x0, y0, idx);
  1054.             }
  1055.         }
  1056.  
  1057.         rel++;
  1058.         pwin->cx++;
  1059.         if( pwin->cx >= pwin->w )
  1060.         {
  1061.             /* If we do not wrap at the right side, just exit */
  1062.             if( pwin->flags & NO_WRAP )
  1063.                 return rel;
  1064.             pwin->cx = 0;
  1065.             pwin->cy++;
  1066.             if( pwin->cy >= pwin->h )
  1067.             {
  1068.                 win_scroll(idx);
  1069.                 pwin->cy--;
  1070.             }
  1071.         }
  1072.     }
  1073.     return rel;
  1074. }
  1075.  
  1076. /************************************************************************
  1077.  *
  1078.  * Name : win_putc
  1079.  *
  1080.  * Entry: Character to print
  1081.  *
  1082.  * Exit : relative offset of the cursor after the output
  1083.  *
  1084.  * Description:
  1085.  *
  1086.  * This routine will put a character to the currently defined window.
  1087.  *
  1088.  ************************************************************************/
  1089.  
  1090. INT32 win_putc(UINT32 idx, UINT8 bChar)
  1091. {
  1092.     struct sWindow *pwin = &p_windows[idx];
  1093.     INT32 rel;
  1094.  
  1095.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1096.     ASSERT(p_windows);            /* And this had better be initialized */
  1097.  
  1098.     if( NULL == pwin->text )
  1099.         return 0;
  1100.  
  1101.     if( pwin->flags & CURSOR_ON )
  1102.         win_set_cursor_char(idx, 0, pwin->flags);
  1103.  
  1104.     rel = win_internal_putchar(idx, bChar);
  1105.  
  1106.     if( pwin->flags & CURSOR_ON )
  1107.         win_set_cursor_char(idx, 1, 0);
  1108.  
  1109.     return rel;
  1110. }
  1111.  
  1112. /************************************************************************
  1113.  *
  1114.  * Name : win_erase_eol
  1115.  *
  1116.  * Entry: Window # and character to fill with
  1117.  *
  1118.  * Exit : None
  1119.  *
  1120.  * Description:
  1121.  *
  1122.  * This routine will fill a character to the end of the line
  1123.  *
  1124.  ************************************************************************/
  1125.  
  1126. void win_erase_eol(UINT32 idx, UINT8 ch)
  1127. {
  1128.     struct sWindow *pwin = &p_windows[idx];
  1129.     UINT32 i, x, y;
  1130.     UINT32 flags_old;
  1131.  
  1132.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1133.     ASSERT(p_windows);            /* And this had better be initialized */
  1134.  
  1135.     if( NULL == pwin->text )
  1136.         return;
  1137.  
  1138.     flags_old = pwin->flags;
  1139.     pwin->flags |= NO_SCROLL;
  1140.  
  1141.     if( pwin->flags & CURSOR_ON )
  1142.         win_set_cursor_char(idx, 0, pwin->flags);
  1143.  
  1144.     /* Do the fill! */
  1145.  
  1146.     x = pwin->cx;
  1147.     y = pwin->cy;
  1148.     for( i = x; i < pwin->w ; i++ )
  1149.         win_internal_putchar(idx, ch);
  1150.  
  1151.     pwin->cx = x;
  1152.     pwin->cy = y;
  1153.     pwin->flags = flags_old;
  1154.  
  1155.     if( pwin->flags & CURSOR_ON )
  1156.         win_set_cursor_char(idx, 1, 0);
  1157. }
  1158.  
  1159. /************************************************************************
  1160.  *
  1161.  * Name : win_set_curpos
  1162.  *
  1163.  * Entry: Window #    and x/y coordinates within the window
  1164.  *
  1165.  * Exit : Nothing
  1166.  *
  1167.  * Description:
  1168.  *
  1169.  * This routine will position the cursor within the Window.
  1170.  *
  1171.  ************************************************************************/
  1172.  
  1173. void win_set_curpos(UINT32 idx, UINT32 x, UINT32 y)
  1174. {
  1175.     struct sWindow *pwin = &p_windows[idx];
  1176.  
  1177.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1178.     ASSERT(p_windows);            /* And this had better be initialized */
  1179.  
  1180.     if( NULL == pwin->text )
  1181.         return;
  1182.  
  1183.     /* Make sure we're in range */
  1184.  
  1185.     /* If we do not wrap at the right side, just exit */
  1186.     if( !(pwin->flags & NO_WRAP) )
  1187.     {
  1188.         if( x >= pwin->w )
  1189.             return;
  1190.         if( y >= pwin->h )
  1191.             return;
  1192.     }
  1193.  
  1194.     win_set_cursor_char(idx, 0, pwin->flags & CURSOR_ON);
  1195.  
  1196.     /* Now put the cursor there */
  1197.  
  1198.     pwin->cx = x;
  1199.     pwin->cy = y;
  1200.     win_set_cursor_char(idx, pwin->flags & CURSOR_ON, 0);
  1201. }
  1202.  
  1203. static char tmp_text[450];
  1204.  
  1205. /************************************************************************
  1206.  *
  1207.  * Name : win_vprintf
  1208.  *
  1209.  * Entry: window # to and format (with optional arguments) to print
  1210.  *
  1211.  * Exit : Nothing
  1212.  *
  1213.  * Description:
  1214.  *
  1215.  * This routine will send a null terminated string to a window
  1216.  *
  1217.  ************************************************************************/
  1218.  
  1219. INT32 win_vprintf(UINT32 idx, const char *fmt, va_list arg)
  1220. {
  1221.     struct sWindow *pwin = &p_windows[idx];
  1222.     char *src = tmp_text;
  1223.     int length = 0;
  1224.  
  1225.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1226.     ASSERT(p_windows);            /* And this had better be initialized */
  1227.  
  1228.     if( NULL == pwin->text )
  1229.         return length;
  1230.  
  1231.     if( pwin->flags & CURSOR_ON )
  1232.         win_set_cursor_char(idx, 0, pwin->flags & CURSOR_ON);
  1233.  
  1234.     length = vsprintf(tmp_text, fmt, arg);
  1235.  
  1236.     while( *src )
  1237.         win_internal_putchar( idx, *src++ );
  1238.  
  1239.     if( pwin->flags & CURSOR_ON )
  1240.         win_set_cursor_char(idx, 1, 0);
  1241.  
  1242.     return length;
  1243. }
  1244.  
  1245.  
  1246. /************************************************************************
  1247.  *
  1248.  * Name : win_printf
  1249.  *
  1250.  * Entry: window # to and format (with optional arguments) to print
  1251.  *
  1252.  * Exit : Nothing
  1253.  *
  1254.  * Description:
  1255.  *
  1256.  * This routine will send a null terminated string to a window
  1257.  *
  1258.  ************************************************************************/
  1259.  
  1260. INT32 DECL_SPEC win_printf(UINT32 idx, const char *fmt, ...)
  1261. {
  1262.     struct sWindow *pwin = &p_windows[idx];
  1263.     char *src = tmp_text;
  1264.     int length = 0;
  1265.     va_list arg;
  1266.  
  1267.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1268.     ASSERT(p_windows);            /* And this had better be initialized */
  1269.  
  1270.     if( NULL == pwin->text )
  1271.         return length;
  1272.  
  1273.     if( pwin->flags & CURSOR_ON )
  1274.         win_set_cursor_char(idx, 0, pwin->flags & CURSOR_ON);
  1275.  
  1276.     va_start(arg, fmt);
  1277.     length = vsprintf(tmp_text, fmt, arg);
  1278.     va_end(arg);
  1279.  
  1280.     while( *src )
  1281.         win_internal_putchar( idx, *src++ );
  1282.  
  1283.     if( pwin->flags & CURSOR_ON )
  1284.         win_set_cursor_char(idx, 1, 0);
  1285.  
  1286.     return length;
  1287. }
  1288.  
  1289. /************************************************************************
  1290.  *
  1291.  * Name : win_set_color
  1292.  *
  1293.  * Entry: Window # and color
  1294.  *
  1295.  * Exit : Nothing
  1296.  *
  1297.  * Description:
  1298.  *
  1299.  * This routine sets the fore- and background colors for
  1300.  * subsequent text outputs (win_putc and win_printf)
  1301.  *
  1302.  ************************************************************************/
  1303.  
  1304. void win_set_color(UINT32 idx, UINT32 color)
  1305. {
  1306.     struct sWindow *pwin = &p_windows[idx];
  1307.  
  1308.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1309.     ASSERT(p_windows);            /* And this had better be initialized */
  1310.  
  1311.     if( NULL == pwin->text )
  1312.         return;
  1313.  
  1314.     pwin->co_text = color;
  1315. }
  1316.  
  1317. /************************************************************************
  1318.  *
  1319.  * Name : win_set_title_color
  1320.  *
  1321.  * Entry: Window # and new title color
  1322.  *
  1323.  * Exit : Nothing
  1324.  *
  1325.  * Description:
  1326.  *
  1327.  * This routine sets the color for title of a window
  1328.  *
  1329.  ************************************************************************/
  1330.  
  1331. void win_set_title_color(UINT32 idx, UINT32 color)
  1332. {
  1333.     struct sWindow *pwin = &p_windows[idx];
  1334.  
  1335.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1336.     ASSERT(p_windows);            /* And this had better be initialized */
  1337.  
  1338.     if( NULL == pwin->text )
  1339.         return;
  1340.  
  1341.     pwin->co_title = color;
  1342.     win_update( idx );
  1343. }
  1344.  
  1345. /************************************************************************
  1346.  *
  1347.  * Name : win_set_frame_color
  1348.  *
  1349.  * Entry: Window # and new frame color
  1350.  *
  1351.  * Exit : Nothing
  1352.  *
  1353.  * Description:
  1354.  *
  1355.  * This routine sets the color for title of a window
  1356.  *
  1357.  ************************************************************************/
  1358.  
  1359. void win_set_frame_color(UINT32 idx, UINT32 color)
  1360. {
  1361.     struct sWindow *pwin = &p_windows[idx];
  1362.  
  1363.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1364.     ASSERT(p_windows);            /* And this had better be initialized */
  1365.  
  1366.     if( NULL == pwin->text )
  1367.         return;
  1368.  
  1369.     pwin->co_frame = color;
  1370.     win_update( idx );
  1371. }
  1372.  
  1373. /************************************************************************
  1374.  *
  1375.  * Name : win_set_cursor
  1376.  *
  1377.  * Entry: Window # and cursor state
  1378.  *
  1379.  * Exit : Nothing
  1380.  *
  1381.  * Description:
  1382.  *
  1383.  * This routine sets the cursor state to on (non zero) or off (zero)
  1384.  *
  1385.  ************************************************************************/
  1386.  
  1387. void win_set_cursor(UINT32 idx, UINT32 state)
  1388. {
  1389.     struct sWindow *pwin = &p_windows[idx];
  1390.     UINT32 cursor;
  1391.  
  1392.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1393.     ASSERT(p_windows);            /* And this had better be initialized */
  1394.  
  1395.     if( NULL == pwin->text )
  1396.         return;
  1397.  
  1398.     if( state )
  1399.         cursor = pwin->flags |= CURSOR_ON;
  1400.     else
  1401.         cursor = pwin->flags &= ~CURSOR_ON;
  1402.  
  1403.     win_set_cursor_char(idx, state, pwin->flags & CURSOR_ON);
  1404.  
  1405.     pwin->flags = cursor;
  1406. }
  1407.  
  1408. /************************************************************************
  1409.  *
  1410.  * Name : win_hide
  1411.  *
  1412.  * Entry: Window # to hide
  1413.  *
  1414.  * Exit : Nothing
  1415.  *
  1416.  * Description:
  1417.  *
  1418.  * This routine will hide a window.
  1419.  *
  1420.  ************************************************************************/
  1421.  
  1422. void win_hide(UINT32 idx)
  1423. {
  1424.     struct sWindow *pwin = &p_windows[idx];
  1425.  
  1426.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1427.     ASSERT(p_windows);            /* And this had better be initialized */
  1428.  
  1429.     /* If it's already hidden, don't hide it again! */
  1430.  
  1431.     if( pwin->flags & HIDDEN )
  1432.         return;
  1433.  
  1434.     /* Otherwise, hide it */
  1435.  
  1436.     win_erase(idx);
  1437.     pwin->flags |= HIDDEN;
  1438. }
  1439.  
  1440. /************************************************************************
  1441.  *
  1442.  * Name : win_show
  1443.  *
  1444.  * Entry: Window # to show
  1445.  *
  1446.  * Exit : Nothing
  1447.  *
  1448.  * Description:
  1449.  *
  1450.  * This routine will show a window.
  1451.  *
  1452.  ************************************************************************/
  1453.  
  1454. void win_show(UINT32 idx)
  1455. {
  1456.     struct sWindow *pwin = &p_windows[idx];
  1457.  
  1458.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1459.     ASSERT(p_windows);            /* And this had better be initialized */
  1460.  
  1461.     /* Don't redraw the window if it's already shown */
  1462.  
  1463.     if( pwin->flags & HIDDEN )
  1464.     {
  1465.         pwin->flags &= ~HIDDEN;
  1466.         win_update_map();
  1467.     }
  1468.  
  1469.     /* But update them */
  1470.     win_update(idx);
  1471. }
  1472.  
  1473. /************************************************************************
  1474.  *
  1475.  * Name : win_set_title
  1476.  *
  1477.  * Entry: Window # and new title
  1478.  *
  1479.  * Exit :
  1480.  *
  1481.  * Description:
  1482.  *
  1483.  * Changes the title of a window and updates the screen
  1484.  *
  1485.  ************************************************************************/
  1486.  
  1487. UINT32 DECL_SPEC win_set_title(UINT32 idx, const char *fmt, ... )
  1488. {
  1489.     struct sWindow *pwin = &p_windows[idx];
  1490.     va_list arg;
  1491.  
  1492.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1493.     ASSERT(p_windows);            /* And this had better be initialized */
  1494.  
  1495.     /* If BORDER_TOP is not set, changing a title makes no sense */
  1496.     if( (pwin->flags & BORDER_TOP) == 0 )
  1497.         return FALSE;
  1498.  
  1499.     va_start(arg, fmt);
  1500.     vsprintf(tmp_text, fmt, arg);
  1501.     va_end(arg);
  1502.  
  1503.     /* If a title is there and did not change, just exit */
  1504.     if( pwin->title && !strcmp(pwin->title, tmp_text) )
  1505.         return TRUE;
  1506.  
  1507.     strcpy( pwin->title, tmp_text );
  1508.  
  1509.     win_update(idx);
  1510.     return TRUE;
  1511. }
  1512.  
  1513. /************************************************************************
  1514.  *
  1515.  * Name : win_get_cx
  1516.  *
  1517.  * Entry: Window #
  1518.  *
  1519.  * Exit : Cursor X
  1520.  *
  1521.  * Description:
  1522.  *
  1523.  * Returns the cursor X coordinate for a window
  1524.  *
  1525.  ************************************************************************/
  1526.  
  1527. UINT32 win_get_cx(UINT32 idx)
  1528. {
  1529.     struct sWindow *pwin = &p_windows[idx];
  1530.  
  1531.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1532.     ASSERT(p_windows);            /* And this had better be initialized */
  1533.  
  1534.     return pwin->cx;
  1535. }
  1536.  
  1537. /************************************************************************
  1538.  *
  1539.  * Name : win_get_cy
  1540.  *
  1541.  * Entry: Window #
  1542.  *
  1543.  * Exit : Cursor Y
  1544.  *
  1545.  * Description:
  1546.  *
  1547.  * Returns the cursor Y coordinate for a window
  1548.  *
  1549.  ************************************************************************/
  1550.  
  1551. UINT32 win_get_cy(UINT32 idx)
  1552. {
  1553.     struct sWindow *pwin = &p_windows[idx];
  1554.  
  1555.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1556.     ASSERT(p_windows);            /* And this had better be initialized */
  1557.  
  1558.     return pwin->cy;
  1559. }
  1560.  
  1561. /************************************************************************
  1562.  *
  1563.  * Name : win_get_cx_abs
  1564.  *
  1565.  * Entry: Window #
  1566.  *
  1567.  * Exit : Cursor X
  1568.  *
  1569.  * Description:
  1570.  *
  1571.  * Returns the screen (absolute) Cursor X coordinate for a window
  1572.  *
  1573.  ************************************************************************/
  1574.  
  1575. UINT32 win_get_cx_abs(UINT32 idx)
  1576. {
  1577.     struct sWindow *pwin = &p_windows[idx];
  1578.     UINT32 x;
  1579.  
  1580.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1581.     ASSERT(p_windows);            /* And this had better be initialized */
  1582.  
  1583.     x = pwin->x + pwin->cx;
  1584.     if( pwin->flags & BORDER_LEFT )
  1585.         x++;
  1586.  
  1587.     return x;
  1588. }
  1589.  
  1590. /************************************************************************
  1591.  *
  1592.  * Name : win_get_cy_abs
  1593.  *
  1594.  * Entry: Window #
  1595.  *
  1596.  * Exit : Cursor Y
  1597.  *
  1598.  * Description:
  1599.  *
  1600.  * Returns the screen (absolute) Cursor Y coordinate for a window
  1601.  *
  1602.  ************************************************************************/
  1603.  
  1604. UINT32 win_get_cy_abs(UINT32 idx)
  1605. {
  1606.     struct sWindow *pwin = &p_windows[idx];
  1607.     UINT32 y;
  1608.  
  1609.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1610.     ASSERT(p_windows);            /* And this had better be initialized */
  1611.  
  1612.     y = pwin->y + pwin->cy;
  1613.     if( pwin->flags & BORDER_TOP )
  1614.         y++;
  1615.  
  1616.     return y;
  1617. }
  1618.  
  1619. /************************************************************************
  1620.  *
  1621.  * Name : win_get_x_abs
  1622.  *
  1623.  * Entry: Window #
  1624.  *
  1625.  * Exit : AbsX
  1626.  *
  1627.  * Description:
  1628.  *
  1629.  * Returns the screen (absolute) X coordinate for a window
  1630.  *
  1631.  ************************************************************************/
  1632.  
  1633. UINT32 win_get_x_abs(UINT32 idx)
  1634. {
  1635.     struct sWindow *pwin = &p_windows[idx];
  1636.     UINT32 x;
  1637.  
  1638.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1639.     ASSERT(p_windows);            /* And this had better be initialized */
  1640.  
  1641.     x = pwin->x;
  1642.     if( pwin->flags & BORDER_LEFT )
  1643.         x++;
  1644.  
  1645.     return x;
  1646. }
  1647.  
  1648. /************************************************************************
  1649.  *
  1650.  * Name : win_get_y_abs
  1651.  *
  1652.  * Entry: Window #
  1653.  *
  1654.  * Exit : AbsY
  1655.  *
  1656.  * Description:
  1657.  *
  1658.  * Returns the screen (absolute) Y coordinate for a window
  1659.  *
  1660.  ************************************************************************/
  1661.  
  1662. UINT32 win_get_y_abs(UINT32 idx)
  1663. {
  1664.     struct sWindow *pwin = &p_windows[idx];
  1665.     UINT32 y;
  1666.  
  1667.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1668.     ASSERT(p_windows);            /* And this had better be initialized */
  1669.  
  1670.     y = pwin->y;
  1671.     if( pwin->flags & BORDER_TOP )
  1672.         y++;
  1673.  
  1674.     return y;
  1675. }
  1676.  
  1677. /************************************************************************
  1678.  *
  1679.  * Name : win_get_w
  1680.  *
  1681.  * Entry: Window #
  1682.  *
  1683.  * Exit : Width
  1684.  *
  1685.  * Description:
  1686.  *
  1687.  * Returns the width of a window
  1688.  *
  1689.  ************************************************************************/
  1690.  
  1691. UINT32 win_get_w(UINT32 idx)
  1692. {
  1693.     struct sWindow *pwin = &p_windows[idx];
  1694.  
  1695.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1696.     ASSERT(p_windows);            /* And this had better be initialized */
  1697.  
  1698.     return pwin->w;
  1699. }
  1700.  
  1701. /************************************************************************
  1702.  *
  1703.  * Name : win_get_h
  1704.  *
  1705.  * Entry: Window #
  1706.  *
  1707.  * Exit : Height
  1708.  *
  1709.  * Description:
  1710.  *
  1711.  * Returns the height of a window
  1712.  *
  1713.  ************************************************************************/
  1714.  
  1715. UINT32 win_get_h(UINT32 idx)
  1716. {
  1717.     struct sWindow *pwin = &p_windows[idx];
  1718.  
  1719.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1720.     ASSERT(p_windows);            /* And this had better be initialized */
  1721.  
  1722.     return pwin->h;
  1723. }
  1724.  
  1725. /************************************************************************
  1726.  *
  1727.  * Name : win_set_w
  1728.  *
  1729.  * Entry: Window # and new width
  1730.  *
  1731.  * Exit : Nothing
  1732.  *
  1733.  * Description:
  1734.  *
  1735.  * Changes the width of a window
  1736.  *
  1737.  ************************************************************************/
  1738.  
  1739. void win_set_w(UINT32 idx, UINT32 w)
  1740. {
  1741.     struct sWindow *pwin = &p_windows[idx];
  1742.  
  1743.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1744.     ASSERT(p_windows);            /* And this had better be initialized */
  1745.  
  1746.     win_erase(idx);
  1747.     pwin->w = w;
  1748.     win_update_map();
  1749.     win_update(idx);
  1750. }
  1751.  
  1752. /************************************************************************
  1753.  *
  1754.  * Name : win_set_h
  1755.  *
  1756.  * Entry: Window # and new height
  1757.  *
  1758.  * Exit : Nothing
  1759.  *
  1760.  * Description:
  1761.  *
  1762.  * Changes the height of a window
  1763.  *
  1764.  ************************************************************************/
  1765.  
  1766. void win_set_h(UINT32 idx, UINT32 h)
  1767. {
  1768.     struct sWindow *pwin = &p_windows[idx];
  1769.     UINT32 yadd;
  1770.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1771.     ASSERT(p_windows);            /* And this had better be initialized */
  1772.  
  1773.     yadd = 0;
  1774.  
  1775.     if( pwin->flags & BORDER_TOP )
  1776.         ++yadd;
  1777.     if( pwin->flags & BORDER_BOTTOM )
  1778.         ++yadd;
  1779.  
  1780.     win_erase(idx);
  1781.     pwin->text = MyReAlloc(pwin->text, screen_w * (h + yadd), "win_set_h()");
  1782.     pwin->attr = MyReAlloc(pwin->attr, screen_w * (h + yadd), "win_set_h()");
  1783.     pwin->h = h;
  1784.     if( pwin->cy >= pwin->h )
  1785.         pwin->cy = pwin->h - 1;
  1786.     win_update_map();
  1787.     win_update(idx);
  1788. }
  1789.  
  1790. /************************************************************************
  1791.  *
  1792.  * Name : win_get_prio
  1793.  *
  1794.  * Entry: Window #
  1795.  *
  1796.  * Exit : Priority of window
  1797.  *
  1798.  * Description:
  1799.  *
  1800.  * Returns the current priority of a window
  1801.  *
  1802.  ************************************************************************/
  1803.  
  1804. UINT8 win_get_prio(UINT32 idx)
  1805. {
  1806.     struct sWindow *pwin = &p_windows[idx];
  1807.  
  1808.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1809.     ASSERT(p_windows);            /* And this had better be initialized */
  1810.  
  1811.     return pwin->prio;
  1812. }
  1813.  
  1814. /************************************************************************
  1815.  *
  1816.  * Name : win_set_prio
  1817.  *
  1818.  * Entry: Window # and new priority
  1819.  *
  1820.  * Exit : Nothing
  1821.  *
  1822.  * Description:
  1823.  *
  1824.  * Changes the priority of a window
  1825.  *
  1826.  ************************************************************************/
  1827.  
  1828. void win_set_prio(UINT32 idx, UINT8 prio)
  1829. {
  1830.     struct sWindow *pwin = &p_windows[idx];
  1831.  
  1832.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1833.     ASSERT(p_windows);            /* And this had better be initialized */
  1834.  
  1835.     if( pwin->prio == prio )
  1836.         return;
  1837.  
  1838.     win_erase(idx);
  1839.     pwin->prio = prio;
  1840.     win_update_map();
  1841.     win_update(idx);
  1842. }
  1843.  
  1844. /************************************************************************
  1845.  *
  1846.  * Name : win_move
  1847.  *
  1848.  * Entry: Window #, new x and y coordinates
  1849.  *
  1850.  * Exit :
  1851.  *
  1852.  * Description:
  1853.  *
  1854.  * Moves a window to a new position
  1855.  *
  1856.  ************************************************************************/
  1857.  
  1858. void win_move(UINT32 idx, UINT32 x, UINT32 y)
  1859. {
  1860.     struct sWindow *pwin = &p_windows[idx];
  1861.  
  1862.     ASSERT(idx < MAX_WINDOWS);    /* This had better be in range */
  1863.     ASSERT(p_windows);            /* And this had better be initialized */
  1864.     win_erase(idx);
  1865.     pwin->x = x;
  1866.     pwin->y = y;
  1867.     win_update_map();
  1868.     win_update(idx);
  1869. }
  1870.  
  1871. /************************************************************************
  1872.  *
  1873.  * Name : win_invalidate_video
  1874.  *
  1875.  * Entry: Nothing
  1876.  *
  1877.  * Exit : Nothing
  1878.  *
  1879.  * Description:
  1880.  *
  1881.  * Invalidates the video memory (eg. after a switch to graphics mode)
  1882.  *
  1883.  ************************************************************************/
  1884.  
  1885. void win_invalidate_video(void)
  1886. {
  1887.  
  1888.     if( p_text == NULL || p_attr == NULL )
  1889.         return;
  1890.  
  1891.     memset( p_text, 0xff, screen_w * screen_h );
  1892.     memset( p_attr, 0xff, screen_w * screen_h );
  1893. }
  1894.  
  1895. #endif
  1896.